#ifndef __EMBEDDING_ENGINE_H__
#define __EMBEDDING_ENGINE_H__ 1

#include <string>

#include "bit_source.h"
#include "properties_reader.h"

#include "types.h"
#include "audio_formats.h"

/**
 * @brief Embedding engine base class
 * @author gpitsch and rpoisel
 */
class IEmbeddingEngine
{
public:
	IEmbeddingEngine() : mPropertiesReader(NULL) { }
	virtual ~IEmbeddingEngine() { }

	/**
	 * pass a reference to a PropertiesReader object to this embedding engine
	 * for handling config files
	 *
	 * @param pPropertiesReader pointer to a PropertiesReader object
	 * instanciated by the EngineFactory
	 */
	virtual void setPropertiesReader(CPropertiesReader* pPropertiesReader);

	/**
	 * get the CPropertiesReader which is used to handle config files for this
	 * embedding engine
	 *
	 * @return the corresponding CPropertiesReader
	 */
	virtual CPropertiesReader* getPropertiesReader() const;

	/** 
	 * @brief get the abbreviation for the properties reader
	 * @return the abbreviation for the properties reader
	 */
	virtual std::string getIniSectionName() const = 0;

	/**
	 * @brief hook call for glue code
	 *
	 * called by the voip phone application to embed data
	 * into the sample before sending a packet
	 * @note this implicitly reads the data to be embedded
	 *       from the IStegIO
	 *
	 * @param pSamples samples to be modified
	 * @param pCount number of samples
	 * @param pLeak number of samples not used between last and current call
	 *
	 * @return >0 for success, 0 for EOF and <0 for an error
	 */
	virtual int embedIntoSamples(int8_t* pSamples, unsigned int pCount, unsigned int pLeak) = 0;
	virtual int embedIntoSamples(uint8_t* pSamples, unsigned int pCount, unsigned int pLeak) = 0;
	virtual int embedIntoSamples(int16_t* pSamples, unsigned int pCount, unsigned int pLeak) = 0;
	virtual int embedIntoSamples(uint16_t* pSamples, unsigned int pCount, unsigned int pLeak) = 0;
	virtual int embedIntoSamples(double* pSamples, unsigned int pCount, unsigned int pLeak) = 0;

	/**
	 * @brief hook call for glue code
	 *
	 * called by the voip phone application to extract data
	 * from the sample after receiving a packet
	 * @note this implicitly writes the extracted data to
	 *       the IStegIO
	 *
	 * @param pSamples samples to be modified
	 * @param pCount number of samples
	 * @param pLeak number of samples not used between last and current call
	 * @param pInBuffer how many samples are left in the buffer.
	 *        If no extra thread is executed for extraction this parameter is always 0.
	 *
	 * @return 0 for success, >0 for success and discard of samples for next
	 *         call, <0 for an error
	 */
	virtual int extractFromSamples(int8_t* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer) = 0;
	virtual int extractFromSamples(uint8_t* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer) = 0;
	virtual int extractFromSamples(int16_t* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer) = 0;
	virtual int extractFromSamples(uint16_t* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer) = 0;
	virtual int extractFromSamples(double* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer) = 0;

	/**
	 * called from the engine factory before destroying the handle
	 */
	virtual void shutdown() = 0;

	/**
	 * called by the protocol engine upon settings change
	 * (e.g. change of embedding parameters)
	 */
	virtual int changeSettings() = 0;

	/**
	 * @brief determine number of processible samples
	 *
	 * called by the samples distributor to determine 
	 * the number of samples which can be processed by the
	 * embedding engine; this can be a dynamic value or 
	 * constant (e.g. for LSB, or echo-hiding) all the time
	 *
	 * @return the number of processible samples
	 */
	virtual int getNumRequiredSamples() = 0;

	/**
	 * @brief determine whether samples should be converted to double before
	 * handed over to an embedding engine
	 *
	 * @return ORIGINAL or MODIFIED
	 */
	virtual NAudioFormats::ESamplesFormat getSamplesFormat() = 0;

protected:
	/**
	 * link to the PropertiesReader object and hence to the config file
	 */
	CPropertiesReader* mPropertiesReader;

private:
	IEmbeddingEngine(const IEmbeddingEngine& );
	IEmbeddingEngine& operator=(const IEmbeddingEngine& );
};

#endif // __EMBEDDING_ENGINE_H__

